/****************************************************************************
*                                                                           *
* Copyright (c) Ionescu M. Marius. All rights reserved(2010).               *
*                                                                           *
****************************************************************************/

// (c) Copyright Romanian Software Company.
// Last Change: 29.01.2010 - by Ionescu Marius.
// All rights reserved.

using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
using System.Web.UI;
using System.ComponentModel;
using System.Collections;
using System.Collections.Specialized;
using System.Web;
using System.Web.UI.HtmlControls;
using System.Data;

namespace NS_Controls
{
    /// <summary>
    /// BulkEditGridView allows users to edit multiple rows of a gridview at once, and have them
    /// all saved.
    /// </summary>
    [
    DefaultEvent("SelectedIndexChanged"),
    Designer("System.Web.UI.Design.WebControls.GridViewDesigner, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"),
    ControlValueProperty("SelectedValue"),
    ]
    public class BulkEditGridView : GridView
    {
        protected DataControlField[] m_Fields = null;

        public DataControlField[] Fields
        {
            get
            {
                if (m_Fields == null)
                {
                    PagedDataSource p = new PagedDataSource();
                    p.DataSource = (IEnumerable)this.DataSource;
                    ArrayList x = (ArrayList)this.CreateColumns(p, this.DataSource != null);
                    m_Fields = new DataControlField[x.Count];
                    x.CopyTo(m_Fields, 0);
                }
                return m_Fields;
            }
            set
            {
                m_Fields = value;
            }
        }

        public bool showEditButton
        {
            get { return (bool)(this.ViewState["showEditButton"] ?? false); }
            set { this.ViewState["showEditButton"] = value; }
        }

        public bool showDeleteButton
        {
            get { return (bool)(this.ViewState["showDeleteButton"] ?? false); }
            set { this.ViewState["showDeleteButton"] = value; }
        }

        //key for the RowInserting event handler list
        public static readonly object RowInsertingEvent = new object();

        private List<int> DirtyRowsIndexes
        {
            get
            {
                if (ViewState["dirtyRows"] == null)
                    ViewState["dirtyRows"] = new List<int>();
                return (List<int>)ViewState["dirtyRows"];
            }
            set { ViewState["dirtyRows"] = value; }
        }

		public List<int> CurrentlyEditedRowsIndexes
		{
			get { return (List<int>)ViewState["beingEditedRows"]; }
			set { ViewState["beingEditedRows"] = value; }
		}

		public bool IsNewRow(int index)
		{
			return NewRowsIndexes.Contains(index);
		}

		public DataRowView PreviewUserInput(int index)
		{
			DataRowView result = ((DataView)this.DataSource).Table.Clone().DefaultView.AddNew();
            ExtractDataRowView(result, InnerTable.Rows[index] as GridViewRow, 0);
			return result;
		}

        private List<int> NewRowsIndexes
        {
            get
            {
                if (ViewState["newRows"] == null)
                    ViewState["newRows"] = new List<int>();
                return (List<int>)ViewState["newRows"];
            }
            set { ViewState["newRows"] = value; }
        }

        public bool AutoSave
        {
            get { return (bool)(this.ViewState["AutoSave"] ?? false); }
            set { this.ViewState["AutoSave"] = value; }
        }

        private TableItemStyle insertRowStyle;

        /// <summary>
        /// Default Constructor
        /// </summary>
        public BulkEditGridView()
        {
        }

        /// <summary>
        /// Modifies the creation of the row to set all rows as editable (if needed).
        /// </summary>
        /// <param name="rowIndex"></param>
        /// <param name="dataSourceIndex"></param>
        /// <param name="rowType"></param>
        /// <param name="rowState"></param>
        /// <returns></returns>
		protected override GridViewRow CreateRow(int rowIndex, int dataSourceIndex, DataControlRowType rowType, DataControlRowState rowState)
		{
			if (EnableEdit && (!NotEditableRows.Contains(dataSourceIndex)) && IsRowBeingEdited(dataSourceIndex))
			{
				rowState = rowState | DataControlRowState.Edit;
			}

            GridViewRow result = base.CreateRow(rowIndex, dataSourceIndex, rowType, rowState | rowState);
			if((this is ExtendedGridView) && !(this as ExtendedGridView).UseDefaultStyle)
				result.BackColor = ((rowState & DataControlRowState.Edit) == DataControlRowState.Edit) ? System.Drawing.Color.LightCyan : System.Drawing.Color.White;
			return result;
		}

		private bool IsRowBeingEdited(int rowIndex)
		{
			if (CurrentlyEditedRowsIndexes == null) //previous code should not care about this!
				return EnableEdit;
			return CurrentlyEditedRowsIndexes.Contains(rowIndex);
		}

        protected override int CreateChildControls(IEnumerable dataSource, bool dataBinding)
        {
            if (dataBinding && dataSource != null)
            {
                List<int> notEditable = new List<int>();
                IEnumerator en = dataSource.GetEnumerator();
                if (en.MoveNext() && en.Current is IEditableData)
                {
                    //TODO: de modificat daca gridul este paginabil, pentru a parcurge numai datele de pe pagina curenta

                    IEditableData edData;
                    int i = 0;
					do
					{
						edData = en.Current as IEditableData;
						if (edData != null && !edData.IsEditable())
							notEditable.Add(i);
						++i;
					}
					while (en.MoveNext());
                }
                NotEditableRows = notEditable;
            }
            return base.CreateChildControls(dataSource, dataBinding);
        }

        public List<GridViewRow> DirtyRows
        {
            get
            {
                List<GridViewRow> drs = new List<GridViewRow>();
                List<int> drI = DirtyRowsIndexes;
                foreach (int rowIndex in drI)
                    drs.Add(this.Rows[rowIndex]);

                return drs;
            }
        }

        /// <summary>
        /// Adds event handlers to controls in all the editable cells.
        /// </summary>
        /// <param name="row"></param>
        /// <param name="fields"></param>
        protected override void InitializeRow(GridViewRow row, DataControlField[] fields)
        {
            base.InitializeRow(row, fields);
            foreach (TableCell cell in row.Cells)
                if (cell.Controls.Count > 0)
                    AddChangedHandlers(cell.Controls);
        }

        /// <summary>
        /// Adds an event handler to editable controls.
        /// </summary>
        /// <param name="controls"></param>
        private void AddChangedHandlers(ControlCollection controls)
        {
            foreach (Control ctrl in controls)
            {
                //Changed the control checks to use interfaces, so that it's more robust.
                if (ctrl is IEditableTextControl)
                {
                    // Drop-down lists, and any list control, implement the IEditableTextControl interface
                    ((IEditableTextControl)ctrl).TextChanged += new EventHandler(this.HandleRowChanged);
                }
                else if (ctrl is ICheckBoxControl)
                {
                    ((ICheckBoxControl)ctrl).CheckedChanged += new EventHandler(this.HandleRowChanged);
                }
                else if (ctrl is HtmlInputText)
                    //Added for BUG#69
                    ((HtmlInputText)ctrl).ServerChange += new EventHandler(this.HandleRowChanged);
                ////could add recursion if we are missing some controls.
                //else if (ctrl.Controls.Count > 0 && !(ctrl is INamingContainer) )
                //{
                //    AddChangedHandlers(ctrl.Controls);
                //}
            }
        }


        /// <summary>
        /// This gets called when a row is changed.  Store the id of the row and wait to update
        /// until save is called.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        void HandleRowChanged(object sender, EventArgs args)
        {
            GridViewRow row = ((Control)sender).NamingContainer as GridViewRow;
            if (null != row)
            {
                if (0 != (row.RowState & DataControlRowState.Insert))
                {
                    int altRowIndex = this.InnerTable.Rows.GetRowIndex(row);
                    if (false == NewRowsIndexes.Contains(altRowIndex))
                        NewRowsIndexes.Add(altRowIndex);
                }
                else
                {
                    if (false == DirtyRowsIndexes.Contains(row.RowIndex))
                        DirtyRowsIndexes.Add(row.RowIndex);
                }

                if (this.AutoSave)
                {
                    DataControlFieldCell dcfc = (DataControlFieldCell)((Control)sender).Parent;
                    DataControlField dcf = dcfc.ContainingField;

                    OrderedDictionary newValues = new OrderedDictionary();
                    dcf.ExtractValuesFromCell(newValues, dcfc, row.RowState, false);

                    if (newValues.Keys.Count > 0)
                    {
                        string[] k = new string[newValues.Keys.Count];
                        newValues.Keys.CopyTo(k, 0);
                        object[] v = new object[newValues.Values.Count];
                        newValues.Values.CopyTo(v, 0);

                        if (EnableEdit)
                        {
                            DataRowView drv = null;
                            if (((DataView)this.DataSource).Count != row.RowIndex + this.PageIndex * this.PageSize)
                            {
                                drv = ((DataView)this.DataSource)[row.RowIndex + this.PageIndex * this.PageSize];

                                if (drv[k[0]] != v[0])
                                    drv[k[0]] = v[0];
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Setting this property will cause the grid to update all modified records when 
        /// this button is clicked.  It currently supports Button, ImageButton, and LinkButton.
        /// If you set this property, you do not need to call save programatically.
        /// </summary>
        [IDReferenceProperty(typeof(Control))]
        public string SaveButtonID
        {
            get { return (string)(this.ViewState["SaveButtonID"] ?? String.Empty); }
            set { this.ViewState["SaveButtonID"] = value; }
        }

        private List<int> NotEditableRows
        {
            get { return (List<int>)(ViewState["NotEditableRows"] ?? new List<int>()); }
            set { ViewState["NotEditableRows"] = value; this.RequiresDataBinding = true; }
        }

        /// <summary>
        /// Attaches an eventhandler to the onclick method of the save button.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            //Attach an event handler to the save button.
            if (false == string.IsNullOrEmpty(this.SaveButtonID))
            {
                IButtonControl btn = (IButtonControl)RecursiveFindControl(this.NamingContainer, this.SaveButtonID);
                if (null != btn)
                    btn.Click += new EventHandler(SaveClicked);
            }
        }

        /// <summary>
        /// Looks for a control recursively up the control tree.  We need this because Page.FindControl
        /// does not find the control if we are inside a masterpage content section.
        /// </summary>
        /// <param name="namingcontainer"></param>
        /// <param name="controlName"></param>
        /// <returns></returns>
        protected Control RecursiveFindControl(Control namingcontainer, string controlName)
        {
            Control c = namingcontainer.FindControl(controlName);

            if (c != null)
                return c;

            if (namingcontainer.NamingContainer != null)
                return RecursiveFindControl(namingcontainer.NamingContainer, controlName);

            return null;
        }

        /// <summary>
        /// Handles the save event, and calls the save method.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SaveClicked(object sender, EventArgs e)
        {
            this.Save();
        }

        /// <summary>
        /// Saves any modified rows.  This is called automatically if the SaveButtonId is set.
        /// </summary>
        public void Save()
        {
            try
            {
                foreach (int row in DirtyRowsIndexes)
                {
                    //TODO: need to check if we really want to not cause validation here.
					//Probably want to pull this from the save button.
                    this.UpdateRow(row, false);
                }

                foreach (int row in NewRowsIndexes)
                {
                    //Make the datasource save a new row.
                    this.InsertRow(row, false);
                }
            }

            finally
            {
                if (DirtyRowsIndexes.Count > 0 || NewRowsIndexes.Count > 0)
                    this.RequiresDataBinding = true;

                DirtyRowsIndexes.Clear();
                NewRowsIndexes.Clear();
            }
        }

        public string SessionKey
        {
            get { return (string)(this.ViewState["SessionKey"] ?? ""); }
            set { this.ViewState["SessionKey"] = value; }
        }

        public int SessionKeyIndex
        {
            get { return (int)(this.ViewState["SessionKeyIndex"] ?? 0); }
            set { this.ViewState["SessionKeyIndex"] = value; }
        }

        public string SessionKeyFilter
        {
            get { return (string)this.Page.Session[this.ClientID + "_SessionKeyFilter"] ?? ""; }
            set { this.Page.Session[this.ClientID + "_SessionKeyFilter"] = value; }
        }

        public override void UpdateRow(int rowIndex, bool causesValidation)
        {
            if (!this.AutoSave)		// update is handled in HandleRowChanged only for the changed cell
                base.UpdateRow(rowIndex, causesValidation);
        }

        public override object DataSource
        {
            get
            {
                if (base.DataSource == null && this.SessionKey != "" && this.Page.Session[this.SessionKey] != null)
                {
                    DataView dv = new DataView(((DataSet)this.Page.Session[this.SessionKey]).Tables[this.SessionKeyIndex]);
                    dv.RowFilter = this.SessionKeyFilter;
                    base.DataSource = dv;
                }
                return base.DataSource;
            }
            set
            {
                if (value != null && !(value is DataView))
                    throw new ApplicationException("GridView DataSource must be a DataView! [ClientID='" + this.ClientID + "']");

                base.DataSource = value;
            }
        }

        /// <summary>
        /// Prepares the <see cref="RowInserting"/> event and calls insert on the DataSource.
        /// </summary>
        /// <param name="rowIndex"></param>
        /// <param name="causesValidation"></param>
        private void InsertRow(int rowIndex, bool causesValidation)
        {
            GridViewRow row = null;

            if ((!causesValidation || (this.Page == null)) || this.Page.IsValid)
            {
                DataSourceView dsv = null;
                bool useDataSource = base.IsBoundUsingDataSourceID;
                if (useDataSource)
                {
                    dsv = this.GetData();
                    if (dsv == null)
                        throw new HttpException("DataSource Returned Null View");
                }
                GridViewInsertEventArgs args = new GridViewInsertEventArgs(rowIndex);
                if (useDataSource)
                {
                    if ((row == null) && (this.InnerTable.Rows.Count > rowIndex))
                        row = this.InnerTable.Rows[rowIndex] as GridViewRow;
                    if (row != null)
                        this.ExtractRowValues(args.NewValues, row, true, false);
                }

                this.OnRowInserting(args);

                if (!args.Cancel && useDataSource)
                    dsv.Insert(args.NewValues, new DataSourceViewOperationCallback(DataSourceViewInsertCallback));
            }
        }

        /// <summary>
        /// Callback for the datasource's insert command.
        /// </summary>
        /// <param name="i"></param>
        /// <param name="ex"></param>
        /// <returns></returns>
        private bool DataSourceViewInsertCallback(int i, Exception ex)
        {
            if (null != ex)
				throw new ApplicationException("DataSourceView Insert failed.", ex);

            return false;
        }


        /// <summary>
        /// Fires the <see cref="RowInserting"/> event.
        /// </summary>
        /// <param name="args"></param>
        protected virtual void OnRowInserting(GridViewInsertEventArgs args)
        {
            Delegate handler = this.Events[RowInsertingEvent];
            if (null != handler)
                handler.DynamicInvoke(this, args);

            DataView dv = ((DataView)this.DataSource).Table.DefaultView;
            DataRowView drv = dv.AddNew();

            GridViewRow r = this.InnerTable.Rows[args.RowIndex] as GridViewRow;

            ulong x = 0;
			bool needsRefresh = true;
			if (dv.Table.Rows.Count == 0)
			{
				ExtractDataRowView(drv, r, x + 1);
			}
			else if (dv.Table.Rows.Count != 0 && dv.Table.Rows[dv.Table.Rows.Count - 1].ItemArray[0].ToString() != "")
			{
				//x = Convert.ToUInt32(dv.Table.Rows[dv.Table.Rows.Count - 1][this.DataKeyNames[0]]);
				x = System.Convert.ToUInt64(dv.Table.Compute("MAX ([" + this.DataKeyNames[0] + "])", ""));
				ExtractDataRowView(drv, r, x + 1);
			}
			else
				needsRefresh = false;

			if (needsRefresh)
			{
				string strFilter = dv.RowFilter;
				dv.RowFilter = "";
				int iLen = dv.Count;
				try
				{
					dv.AddNew();
					dv.Delete(iLen);
				}
				catch (System.Data.NoNullAllowedException) { }
				dv.RowFilter = strFilter;
			}

            this.PageIndex = this.PageCount - 1;
        }

        private void ExtractDataRowView(DataRowView drv, GridViewRow r, ulong x)
        {
            try
            {
                DataControlField[] fields = this.Fields;
                for (int i = 0; i < fields.Length; ++i)
                {
                    DataControlField dcf = fields[i];

                    if (dcf is CheckBoxField)
                    {
                        if (!((CheckBoxField)dcf).ReadOnly)
                        {
                            string strDataField = ((CheckBoxField)dcf).DataField;
                            if (r.Cells[i].HasControls())
                            {
                                Control ctrl = r.Cells[i].Controls[0];
                                if (ctrl is CheckBox)
                                {
                                    bool bValue = ((CheckBox)r.Cells[i].Controls[0]).Checked;
                                    if ((bool)drv[strDataField] != bValue)
                                        drv[strDataField] = bValue;
                                }
                            }
                        }
                    }

                    else if (dcf is TextBoxField)
                    {
                        if (!((TextBoxField)dcf).ReadOnly)
                        {
                            TextBoxField f = dcf as TextBoxField;
                            string strDataField = f.DataField;
                            string strValue = null;
                            if (r.Cells[i].HasControls())
                            {
                                Control ctrl = r.Cells[i].Controls[0];
                                if (ctrl is TextBox)
                                {
                                    strValue = ((TextBox)r.Cells[i].Controls[0]).Text;
                                    if (string.Format(f.DataFormatString, drv[strDataField]) != strValue)
                                        drv[strDataField] = strValue;
                                }
                            }
                        }
                    }

                    else if (dcf is HyperLinkFieldX)
                    {
                        HyperLinkFieldX f = dcf as HyperLinkFieldX;
                        string strDataField = f.DataField;
                        string strValue = null;
                        if (r.Cells[i].HasControls())
                        {
                            Control ctrl = r.Cells[i].Controls[0];
                            if (ctrl is TextBox)
                            {
                                strValue = ((TextBox)r.Cells[i].Controls[0]).Text;
                                if (string.Format(f.DataTextFormatString, drv[strDataField]) != strValue)
                                    drv[strDataField] = strValue;
                            }
                        }
                    }

                    else if (dcf is DropDownField)
                    {
                        if (!((DropDownField)dcf).ReadOnly)
                        {
                            DropDownField f = dcf as DropDownField;
                            string strDataField = f.DataField;
                            string strValue = null;
                            if (r.Cells[i].HasControls())
                            {
                                Control ctrl = r.Cells[i].Controls[0];
                                if (ctrl is DropDownList)
                                {
                                    strValue = ((DropDownList)r.Cells[i].Controls[0]).SelectedValue;
                                    if (string.Format(f.DataFormatString, drv[strDataField]) != strValue)
                                        drv[strDataField] = strValue;
                                }
                            }
                        }
                    }

                    else if (dcf is AutoGeneratedField)
                    {
                        if (r.Cells[i].Controls.Count > 0)
                        {
                            AutoGeneratedField aut = dcf as AutoGeneratedField;
                            string strDataField = aut.DataField;
                            string strValue = "";
                            bool valBool;
                            if (r.Cells[i].HasControls())
                            {
                                if (r.Cells[i].Controls[0] is TextBox)
                                {
                                    strValue = ((TextBox)r.Cells[i].Controls[0]).Text;
                                    if (string.Format(aut.DataFormatString, drv[strDataField]) != strValue)
                                    {
                                        drv[strDataField] = strValue;
                                    }
                                }
                                else if (r.Cells[i].Controls[0] is Label)
                                {
                                    if (strDataField == "ID")
                                    {
                                        drv[strDataField] = x;
                                    }
                                }
                                else if (r.Cells[i].Controls[0] is CheckBox)
                                {
                                    valBool = ((CheckBox)r.Cells[i].Controls[0]).Checked;
                                    drv[strDataField] = valBool;
                                }
                            }
                        }
                    }
                    else if (dcf is DateTimeField)
                    {
                        if (!((DateTimeField)dcf).ReadOnly)
                        {
                            DateTimeField f = dcf as DateTimeField;
                            string strDataField = f.DataField;
                            string strValue = null;
                            if (r.Cells[i].HasControls())
                            {
                                Control ctrl = r.Cells[i].Controls[0];
                                if (ctrl is TextBox)
                                {
                                    strValue = ((TextBox)r.Cells[i].Controls[0]).Text;
                                    if (string.Format(f.DataFormatString, drv[strDataField]) != strValue)
                                        drv[strDataField] = strValue;
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception)
            {
                drv.CancelEdit();
                throw;
            }
        }

        /// <summary>
        /// Event fires when new row has been edited, and save is clicked.
        /// </summary>
        public event GridViewInsertEventHandler RowInserting
        {
            add { this.Events.AddHandler(RowInsertingEvent, value); }
            remove { this.Events.RemoveHandler(RowInsertingEvent, value); }
        }

        /// <summary>
        /// Access to the GridView's inner table.
        /// </summary>
        protected Table InnerTable
        {
            get
            {
                if (false == this.HasControls())
                    return null;

                return (Table)this.Controls[0];
            }
        }

        /// <summary>
        /// Enables inline inserting.  Off by default.
        /// </summary>
        [Category("Extended")]
        public bool EnableInsert
        {
            get { return (bool)(this.ViewState["EnableInsert"] ?? false); }
            set { this.ViewState["EnableInsert"] = value; this.RequiresDataBinding = true; }
        }


        /// <summary>
        /// Enables edit for all rows
        /// </summary>
        [Category("Extended")]
        public bool EnableEdit
        {
            get { return (bool)(this.ViewState["EnableEdit"] ?? false); }
            set { this.ViewState["EnableEdit"] = value; this.RequiresDataBinding = true; }
        }

        [Category("Extended")]
        public int InsertRowCount
        {
            get { return (int)(this.ViewState["InsertRowCount"] ?? 1); }
            set
            {
                if (value < 1)
                    throw new ArgumentOutOfRangeException("value must be >= 1");

                this.ViewState["InsertRowCount"] = value;
                this.RequiresDataBinding = true;
            }
        }

        /// <summary>
        /// We have to recreate our insert row so we can load the postback info from it.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected override void OnPagePreLoad(object sender, EventArgs e)
        {
            base.OnPagePreLoad(sender, e);

            if (this.EnableInsert && this.Page.IsPostBack)
                for (int i = 0; i < this.InsertRowCount; ++i)
                    this.CreateInsertRow();
        }

        /// <summary>
        /// After the controls are databound, add a row to the end.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnDataBound(EventArgs e)
        {
            if (this.EnableInsert)
                for (int i = 0; i < this.InsertRowCount; ++i)
                    this.CreateInsertRow();

            base.OnDataBound(e);
        }

        /// <summary>
        /// Creates the insert row and adds it to the inner table.
        /// </summary>
        protected virtual void CreateInsertRow()
        {
            GridViewRow row = this.CreateRow(this.Rows.Count, -1, DataControlRowType.DataRow, DataControlRowState.Insert);

            DataControlField[] fields = this.Fields;
            row.ApplyStyle(this.insertRowStyle);
            this.InitializeRow(row, fields);

            if (this.Rows.Count == 0)
            {
                this.Controls.Add(new Table());
                GridViewRow header = this.CreateRow(0, -1, DataControlRowType.Header, DataControlRowState.Normal);
                this.InitializeRow(header, fields);
                this.InnerTable.Rows.AddAt(0, header);
            }

            NewRowsIndexes.Clear();

            int index = this.InnerTable.Rows.Count - 1 - (this.ShowFooter ? 1 : 0) - (this.AllowPaging ? 1 : 0);
            this.InnerTable.Rows.AddAt(index, row);
			if (showEditButton && showDeleteButton)
			{
				RemoveControl(this.InnerTable.Rows[index], 0, 1);
				RemoveControl(this.InnerTable.Rows[index], 1, 1);
				RemoveControl(this.InnerTable.Rows[index], 2, 0);
			}
			else if (showEditButton || showDeleteButton)
			{
				RemoveControl(this.InnerTable.Rows[index], 0, 1);
				RemoveControl(this.InnerTable.Rows[index], 1, 0);
			}
			else
				RemoveControl(this.InnerTable.Rows[index], 0, 0);

            for (int i = 0; i < fields.Length; ++i)
            {
                DataControlField dcf = fields[i];
                if (dcf.HeaderText == "ID")
                {
                    Label lbl = new Label();

                    if (this.InnerTable.Rows[index].Cells[i].Controls.Count > 0 )
                        if (this.InnerTable.Rows[index].Cells[i].Controls[0] is TextBox && showDeleteButton)
                            this.InnerTable.Rows[index].Cells[i].Controls.RemoveAt(0);
                    this.InnerTable.Rows[index].Cells[i].Controls.Add(lbl);
                }
            }
        }

		private void RemoveControl(TableRow container, int cell, int control)
		{
			//NB: skip this if ALL the fields are auto-generated:
			int hiddenCols = (this is ExtendedGridView ? (this as ExtendedGridView).HiddenColumns.Length : 0);
			if (container.Cells.Count > (Fields.Length - hiddenCols))
				return;
			//otherwise, remove the targetted control:
			if ((container.Cells.Count > cell) && (container.Cells[cell].Controls.Count > control))
				container.Cells[cell].Controls.RemoveAt(control);
		}

        [
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
        Category("Styles"),
        PersistenceMode(PersistenceMode.InnerProperty),
        NotifyParentProperty(true),
        Description("GridView_InsertRowStyle")
        ]
        public TableItemStyle InsertRowStyle
        {
            get
            {
                if (this.insertRowStyle == null)
                {
                    this.insertRowStyle = new TableItemStyle();
                    if (base.IsTrackingViewState)
                    {
                        ((IStateManager)this.insertRowStyle).TrackViewState();
                    }
                }
                return this.insertRowStyle;
            }
        }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="args"></param>
    public delegate void GridViewInsertEventHandler(object sender, GridViewInsertEventArgs args);

    /// <summary>
	/// The type of object to use for the second parameter to RowInserting events.
    /// </summary>
    public class GridViewInsertEventArgs : CancelEventArgs
    {
        private int _rowIndex;
        private IOrderedDictionary _values;

        public GridViewInsertEventArgs(int rowIndex)
            : base(false)
        {
            this._rowIndex = rowIndex;
        }

        /// <summary>
        /// Gets a dictionary containing the revised values of the non-key field name/value
        /// pairs in the row to update.
        /// </summary>
        public IOrderedDictionary NewValues
        {
            get
            {
                if (this._values == null)
                    this._values = new OrderedDictionary();

                return this._values;
            }
        }

        /// <summary>
        /// Gets the index of the row being updated.
        /// </summary>
        public int RowIndex { get { return this._rowIndex; } }
    }
}
